#!/usr/bin/env python
# -*- coding:utf8 -*-
# uncompyle6 version 2.15.1
# Python bytecode 2.7 (62211)
# Decompiled from: Python 2.7.10 (default, Jul  1 2017, 13:36:56)
# [GCC 4.4.6 20110731 (Red Hat 4.4.6-4)]
# Embedded file name: ./esb/esb/management/utils/api_docs.py
# Compiled at: 2017-11-16 15:44:28
import textwrap, markdown
from jinja2 import Template
from esb.bkcore.models import ComponentAPIDoc, ESBChannel
from esb.utils import channel_tools
from common.base_utils import get_md5, smart_unicode
from esb.utils import config

class ApiDocManager(object):

    def __init__(self):
        self.is_update_all_api_doc = False
        self.all_doc_md_md5 = self.get_all_doc_md_md5()

    def get_api_doc(self, comp_codename):
        api_data = channel_tools.get_api_data_with_md(comp_codename)
        return self.get_document(api_data)

    def get_document(self, api_data):
        doc_md = self.get_doc_md(api_data)
        if not doc_md:
            return
        if not (self.is_update_all_api_doc or self.is_api_doc_changed(api_data['comp_codename'], doc_md)):
            raise DocNotChangedException
        api_doc = APIDoc(doc_md, api_data)
        api_doc = api_doc.get_doc_info()
        api_data.update(api_doc)
        return api_data

    def get_doc_md(self, api_data):
        comp_doc = textwrap.dedent(api_data['comp_doc']).strip()
        if not comp_doc:
            return
        doc_common_args = self.get_doc_common_args()
        doc_md = Template(comp_doc).render(common_args_desc=textwrap.dedent(doc_common_args))
        return doc_md

    def get_doc_common_args(self):
        return config.ESB_CONFIG['config'].get('doc_common_args', '')

    def is_api_doc_changed(self, comp_codename, doc_md):
        new_doc_md_md5 = get_md5(doc_md)
        key = comp_codename
        return new_doc_md_md5 != self.all_doc_md_md5.get(key)

    def get_all_doc_md_md5(self):
        components = ESBChannel.objects.values_list('id', 'component_codename')
        components = dict(components)
        all_doc_md_md5 = {}
        api_docs = ComponentAPIDoc.objects.values('component_id', 'doc_md_md5')
        for api_doc in api_docs:
            component_id = api_doc['component_id']
            key = components.get(component_id)
            if not key:
                continue
            all_doc_md_md5[key] = api_doc['doc_md_md5']

        return all_doc_md_md5


API_URL = '### 请求地址{api_url}'
API_METHOD = '### 请求方法{api_method}'

class APIDoc(object):

    def __init__(self, doc_md, api_data):
        self.doc_md = doc_md
        self.api_data = api_data
        self.raw_doc_md_md5 = get_md5(self.doc_md)
        self.update_doc_md()

    def get_doc_html(self):
        return self.format_md_to_html(self.doc_md)

    def get_doc_info(self):
        return {'doc_md': self.doc_md,
           'doc_html': self.format_md_to_html(self.doc_md),
           'raw_doc_md_md5': self.raw_doc_md_md5
           }

    def update_doc_md(self):
        self.clear_api_flag()
        self.add_api_method()
        self.add_url()

    def add_url(self):
        api_url = ('/api/c/compapi/{system_name}/{api_name}/').format(system_name=self.api_data['system_name'].lower(), api_name=self.api_data['api_name'])
        url_content = API_URL.format(api_url=api_url)
        self.doc_md = self.insert_to_doc_md(self.doc_md, url_content)

    def add_api_method(self):
        api_method = self.api_data['suggest_method'].upper()
        api_method_content = API_METHOD.format(api_method=api_method)
        self.doc_md = self.insert_to_doc_md(self.doc_md, api_method_content)

    def insert_to_doc_md(self, doc_md, content):
        return u'%s%s' % (smart_unicode(content), doc_md)

    def clear_api_flag(self):
        doc_md = self.doc_md.splitlines()
        for index, line in enumerate(doc_md):
            if line.startswith('api'):
                doc_md[index] = ''
            else:
                break

        self.doc_md = ('\n').join(doc_md).strip()

    def format_md_to_html(self, doc_md):
        doc_html = markdown.markdown(doc_md, extensions=[
         'tables',
         'attr_list',
         'fenced_code',
         'smart_strong',
         'codehilite',
         'toc'])
        return doc_html


class DocNotChangedException(Exception):
    pass